﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BooruViewer.Models
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class Gelbooru
    {
        [JsonProperty("source")]
        public string Source { get; set; }

        [JsonProperty("directory")]
        public string Directory { get; set; }

        [JsonProperty("hash")]
        public string Hash { get; set; }

        [JsonProperty("height")]
        public long Height { get; set; }

        [JsonProperty("id")]
        public long Id { get; set; }

        [JsonProperty("image")]
        public string Image { get; set; }

        [JsonProperty("change")]
        public long Change { get; set; }

        [JsonProperty("owner")]
        public string Owner { get; set; }

        [JsonProperty("parent_id")]
        public object ParentId { get; set; }

        [JsonProperty("rating")]
        public string Rating { get; set; }

        [JsonProperty("sample")]
        public bool Sample { get; set; }

        [JsonProperty("sample_height")]
        public long SampleHeight { get; set; }

        [JsonProperty("sample_width")]
        public long SampleWidth { get; set; }

        [JsonProperty("score")]
        public long Score { get; set; }

        [JsonProperty("tags")]
        public string Tags { get; set; }

        [JsonProperty("width")]
        public long Width { get; set; }

        [JsonProperty("file_url")]
        public Uri FileUrl { get; set; }

        [JsonProperty("created_at")]
        public string CreatedAt { get; set; }
    }

    public partial class Gelbooru
    {
        public static Gelbooru[] FromJson(string json) => JsonConvert.DeserializeObject<Gelbooru[]>(json, GelConverter.Settings);
    }

    internal static class GelConverter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters = {
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }

    public static class GelHelpers
    {
        /// <summary>
        /// Coverts the Danbooru array object to a list of BImage objects
        /// </summary>
        /// <param name="gel"></param>
        /// <returns></returns>
        public static List<BImage> GelToImages(this Gelbooru[] gel)
        {
            List<BImage> imgs = new List<BImage>();

            int i = 1;
            foreach (var g in gel)
            {
                var tags = g.Tags.Split(' ');

                imgs.Add(new BImage(
                    g.Id.ToString(),
                    g.FileUrl.ToString(),
                    g.FileUrl.ToString(),
                    new []{g.Owner},
                    tags, 
                    "image",
                    g.Score
                ));
                i++;
            }

            return imgs;
        }

        /// <summary>
        /// Gets a Query object and parses it into a Danbooru-specific query string
        /// </summary>
        /// <param name="q"></param>
        /// <returns></returns>
        public static string BuildGel(this Query q, string url = "https://gelbooru.com")
        {
            // Base endpoint
            string query = url+"/index.php?page=dapi&s=post&q=index&json=1&tags=";

            // Tags
            query += q.Tags
                    .TrimEnd(' ')
                    .Replace(" ", "%20");

            // Rating
            string rating = "";

            if (q.Ratings.Contains(Rating.Safe))
                rating += "rating:s ";
            if (q.Ratings.Contains(Rating.Questionable))
                rating += "rating:q ";
            if (q.Ratings.Contains(Rating.Explicit))
                rating += "rating:e ";
            rating = rating.TrimEnd(' ').Replace(" ", "%20~");

            if (rating != "")
                rating = "+" + rating;

            query += rating;

            //Prepare score query
            string score = "";

            if (q.MinScore != null && q.MaxScore != null)
            {
                score += "score:>=";
                score += q.MinScore;
                score += "+score:<=";
                score += q.MaxScore;
            }
            else
            {
                if (q.MinScore != null)
                {
                    score += "score:>=";
                    score += q.MinScore;
                }

                if (q.MaxScore != null)
                {
                    score += "+score:<=";
                    score += q.MaxScore;
                }
            }

            if (score != "")
                score = "+score:" + score;

            query += score;

            // Add page number
            query += "&pid=" + q.Page;
            
            // Add limit
            query += "&limit=30";

            return query;

        }
    }
}
